// const puppeteer = require("puppeteer-core");
const { chromium } = require("playwright");
const Axios = require("axios");
const md5 = require("md5");
const utils = require("./utils");

// console.log(puppeteer.executablePath());

const API_BASE = "https://tablo.fun/app/43";

const axios = Axios.create({
  baseURL: API_BASE,
});

const { inLocal } = utils;
const puppOpts = {
  headless: "new",
  executablePath:
    "/Users/mac/.cache/puppeteer/chrome/mac-125.0.6422.78/chrome-mac-x64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing",
};

if (!inLocal) {
  puppOpts.executablePath =
    "/home/ubuntu/.cache/puppeteer/chrome/linux-121.0.6167.85/chrome-linux64/chrome";
}
console.log(puppOpts);

module.exports = {
  inLocal,
  log(...args) {
    if (inLocal) {
      console.log(...args);
    }
  },
  getRow(params) {
    return axios
      .get("/data/item/pupp-link", { params })
      .then((res) => res.data.row);
  },
  postRow(body) {
    return axios.post("/data/upsert/pupp-link", body).then((res) => res.data);
  },
  async getData(query, ip) {
    let { url } = query;
    if (!url) {
      throw new Error("no url");
    }
    if (!/^http/.test(url)) {
      url = "https://" + url;
    }
    if (query.view_w) {
      query.view_w = utils.checkSize("view_w", query.view_w, [370, 2000]);
    }
    if (query.view_h) {
      query.view_h = utils.checkSize("view_h", query.view_h, [640, 1500]);
    }
    const hash = md5(JSON.stringify(query)).substring(0, 8);
    const row = await this.getRow({
      hash,
    });
    if (row && row.status != 3) {
      if (row.status != 2 && Date.now() - row.createdAt > 60e3) {
        await this.postRow({
          id: row.id,
          status: 3,
          extra: {
            msg: "timeout",
          },
        });
      } else {
        return this.setData(row);
      }
    }
    delete query.url;
    let data = await this.postRow({
      hash,
      url,
      ip,
      query,
    });
    data = await this.putData(data);
    return this.setData(data);
  },
  async setData(data) {
    try {
      const { shot } = data;
      if (shot) {
        const { img, pdf } = shot;
        data._shotImg = await utils.getShotUrl(img);
        data._shotPdf = await utils.getShotUrl(pdf);
      }
    } catch (error) {
      console.log(error.message);
    }
    return data;
  },
  async putData(data) {
    try {
      return this.getPage(data);
    } catch (error) {
      return this.postRow({
        id: data.id,
        extra: {
          msg: error.message,
        },
        status: 3,
      });
    }
  },
  async getPage(data) {
    const { id, url, query, hash } = data;
    if (id > 1000) {
      throw new Error("服务维护中");
    }
    const mat = /^(https?:)\/\/([^\/]+)/.exec(url);
    if (!mat) {
      throw new Error("invalid url");
    }

    let meta = {
      protocol: mat[1],
      host: mat[2],
    };
    query.id = id;
    query.host = meta.host;
    query.hash = hash;
    query.url = url;
    await this.postRow({
      id,
      status: 1,
      meta,
    });
    // const browser = await puppeteer.launch(puppOpts);
    const browser = await chromium.launch();
    const page = await browser.newPage();
    // await page.emulateTimezone(query.timezone || "Asia/Shanghai");
    // const device = puppeteer.devices[query.device];
    // if (device) {
    //   await page.emulate(device);
    // } else {
    // }
    // await page.setViewport({
    //   width: query.view_w || 1200,
    //   height: query.view_h || 800,
    // });
    await page.goto(url, {
      waitUntil: query.wait_until || "networkidle", // domcontentloaded, networkidle0
    });
    const title = await page.title();
    this.log(url, title);
    await this.setMeta(page, meta);
    await this.postRow({
      id,
      title,
      meta,
    });
    if (!query.in_pc && meta.viewport?.includes("scale=1")) {
      query.pdf_format = query.pdf_format || "A5";
    }
    const { maxH } = await utils.autoScroll(page); // 滚动到最底，再滚回顶部，尽量加载所有内容（包括懒加载图片等）
    await this.putHtmlData(page, query);
    query.shot_full = !!query.shot_full || maxH < 1000;
    const result = await this.putShot(page, query);
    this.log(url, "end");
    browser.close();
    return result;
  },
  async setMeta(page, meta) {
    const icons = await utils.getIcons(page);
    if (icons.length) {
      meta.icons = icons;
    }
    const info = await utils.getMeta(page);
    Object.assign(meta, info);
  },
  async putHtmlData(page, query) {
    const data = {
      id: query.id,
    };
    const checkExtra = await utils.checkPage(page, query);
    data.title = await page.title(); // 经过页面滚动后，再次获取（有些网页需加载后才能获取标题）
    data.links = await utils.getLinks(page, query);
    data.imgs = await utils.getImgs(page, query);
    data.txts = await utils.getTxts(page, query);
    const moreExtra = await utils.getExtra(page, query);
    data.extra = {
      ...checkExtra,
      ...moreExtra,
    };
    await this.postRow(data);
  },
  async putShot(page, query) {
    const shot = await utils.getShot(page, query);
    return this.postRow({
      id: query.id,
      shot,
      status: 2,
    });
  },
};
